package com.ruoyi.ldzlsc.service.Impl;

import com.ruoyi.common.core.domain.UR;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.ldzlsc.domain.*;
import com.ruoyi.ldzlsc.domain.dto.WorkReportDto;
import com.ruoyi.ldzlsc.domain.vo.WorkOrderVO;
import com.ruoyi.ldzlsc.domain.vo.WorkOrderTaskDetailVO;
import com.ruoyi.ldzlsc.domain.vo.ScBomVo;
import com.ruoyi.ldzlsc.domain.vo.ScBomDetailVo;
import com.ruoyi.ldzlsc.mapper.*;
import com.ruoyi.ldzlsc.service.IScWorkReportService;

import com.ruoyi.system.api.BasicService;
import com.ruoyi.system.api.DetectService;
import com.ruoyi.system.api.InventoryService;
import com.ruoyi.system.api.domain.CkBatch;
import com.ruoyi.system.api.domain.QcIpqcDto;
import com.ruoyi.system.api.domain.QcTemplateProductDto;
import com.ruoyi.ldzlsc.service.WebSocketService;
import com.ruoyi.system.api.domain.QcRqcDto;
import com.ruoyi.system.api.domain.BasicWlgl;
import java.util.List;
import java.util.ArrayList;
import java.math.RoundingMode;
import java.util.Map;
import java.util.HashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;

/**
 * 报工服务实现类
 * 提供报工相关的业务逻辑处理
 */
@Service
public class ScWorkReportServiceImpl implements IScWorkReportService {

    @Autowired
    private IScWorkReportMapper scWorkReportMapper;

    @Autowired
    private ScWorkOrderTaskMapper scWorkOrderTaskMapper;

    @Autowired
    private ScWorkOrderMapper scWorkOrderMapper;

    @Autowired
    private ScProductionPlanMapper scProductionPlanMapper;

    @Autowired
    private ScProductionOrderMapper scProductionOrderMapper;

    @Resource
    private InventoryService inventoryService;

    @Resource
    private BasicService basicService;

    @Resource
    private DetectService detectService;

    @Autowired
    private WebSocketService webSocketService;


    @Autowired
    private ScBomMapper scBomMapper;

    @Autowired
    private CkItemRecptMapper ckItemRecptMapper;

    @Autowired
    private CkItemRecptLineMapper ckItemRecptLineMapper;

    @Autowired
    private ScMaterialIssueDetailMapper scMaterialIssueDetailMapper;

    @Autowired
    private ScMaterialReturnMapper scMaterialReturnMapper;

    @Autowired
    private ScMaterialReturnDetailMapper scMaterialReturnDetailMapper;



    /**
     * 报工操作
     * @param workReportDto 报工数据传输对象
     * @return 操作结果（1表示成功）
     * @throws ServiceException 业务异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int report(WorkReportDto workReportDto) {
        // 1. 数据校验
        if (workReportDto.getWorkOrderTaskId() == null) {
            throw new ServiceException("工序任务ID不能为空");
        }
        ScWorkOrderTask task = scWorkOrderTaskMapper.selectScWorkOrderTaskByWorkOrderTaskId(workReportDto.getWorkOrderTaskId());
        if (task == null) {
            throw new ServiceException("工序任务不存在");
        }

        // 2. 创建报工记录
        ScWorkReport report = createWorkReport(workReportDto, task);
        scWorkReportMapper.insertScWorkReport(report);

        // 3. 更新工序任务（会自动设置为待质检状态并推送WebSocket消息）
        updateTaskProgress(workReportDto, task);

        // 4. 创建生产质检单
        createQualityCheckOrder(task, workReportDto);

        // 5. 创建退料记录
        createMaterialReturnRecord(task, workReportDto);

        // 6. 直接创建退料入库记录
        createReturnInboundRecordDirectly(task, workReportDto);

        return 1;
    }

    /**
     * 创建质检单
     * @param task 工序任务
     * @param workReportDto 报工数据
     * @return 质检结果预期（true=预期合格，false=预期不合格）
     */
    private boolean createQualityCheckOrder(ScWorkOrderTask task, WorkReportDto workReportDto) {
        try {
            // 1. 获取工序任务详细信息（包含产品信息）
            WorkOrderTaskDetailVO taskDetail = scWorkOrderTaskMapper.selectWorkOrderTaskDetailById(task.getWorkOrderTaskId());
            if (taskDetail == null || taskDetail.getWorkOrderInfo() == null) {
                System.err.println("无法获取工序任务详细信息，跳过质检");
                return true; // 默认合格
            }

            WorkOrderTaskDetailVO.WorkOrderInfo workOrderInfo = taskDetail.getWorkOrderInfo();
            System.out.println("工单ID: " + workOrderInfo.getWorkOrderId());
            System.out.println("产品ID: " + workOrderInfo.getProductId());
            System.out.println("产品编码: " + workOrderInfo.getProductCode());

            // 2. 查询产品的检测方案 - 使用任务关联的产品ID
            QcTemplateProductDto template = null;
            if (workOrderInfo.getProductId() != null) {
                template = detectService.selectQcTemplateProductProductCode(workOrderInfo.getProductId());
                System.out.println("检测方案查询结果: " + (template != null ? "找到" : "未找到"));
            }

            // 如果没有检测方案，创建一个默认的检测方案
            if (template == null) {
                System.out.println("产品无检测方案，创建默认检测方案");
                template = new QcTemplateProductDto();
                template.setTemplate_id(1L); // 设置一个默认的模板ID
                template.setQuantity_check_num(1);
                template.setQuantity_unqualified_num(0);
                template.setCr_rate(0.0);
                template.setMaj_rate(0.0);
                template.setMin_rate(0.0);
                template.setProduct_id(workOrderInfo.getProductId());
                template.setProduct_code(workOrderInfo.getProductCode());
                template.setProduct_name(workOrderInfo.getProductName());
                template.setProduct_sfn(workOrderInfo.getSpecification());
                template.setUnit(workOrderInfo.getUnit());
            }

            // 3. 创建过程检验单
            QcIpqcDto ipqcDto = createIpqcDto(task, taskDetail, workReportDto, template);
            System.out.println("创建检验单: " + ipqcDto.getIpqcCode());

            // 4. 调用质检接口创建检验单
            AjaxResult result = detectService.add(ipqcDto);
            if (result == null || !result.isSuccess()) {
                System.err.println("创建检验单失败: " + (result != null ? result.get("msg") + ", 详细信息: " + result : "返回为空"));
                return true; // 创建失败默认合格
            }

            System.out.println("生产检验单创建成功，结果: " + result);

            // 注意：退料质检单已移除，改为直接创建退料入库记录

            return true; // 创建成功，等待实际检验结果

        } catch (Exception e) {
            System.err.println("创建质检单异常: " + e.getMessage());
            e.printStackTrace();
            return true; // 异常情况默认合格，避免影响正常流程
        }
    }


    /**
     * 创建过程检验单DTO
     */
    private QcIpqcDto createIpqcDto(ScWorkOrderTask task, WorkOrderTaskDetailVO taskDetail, WorkReportDto workReportDto, QcTemplateProductDto template) {
        QcIpqcDto ipqcDto = new QcIpqcDto();

        WorkOrderTaskDetailVO.WorkOrderInfo workOrderInfo = taskDetail.getWorkOrderInfo();
        WorkOrderTaskDetailVO.TaskInfo taskInfo = taskDetail.getTaskInfo();

        // 基本信息
        String ipqcCode = "IPQC-" + workOrderInfo.getWorkOrderCode() + "-" + taskInfo.getProcessCode() + "-" + System.currentTimeMillis();
        ipqcDto.setIpqcCode(ipqcCode);
        ipqcDto.setIpqcName("过程检验-" + workOrderInfo.getWorkOrderName() + "-" + taskInfo.getProcessName());
        ipqcDto.setIpqcType("3"); // 2=已提交

        // 模板信息
        ipqcDto.setTemplateId(template.getTemplate_id() != null ? template.getTemplate_id() : 1L);

        // 来源单据信息
        ipqcDto.setSourceDocId(task.getWorkOrderTaskId());
        ipqcDto.setSourceDocType("3");
        ipqcDto.setSourceDocCode(task.getTaskCode());
        ipqcDto.setSourceLineId(task.getWorkOrderTaskId());

        // 工单信息
        ipqcDto.setWorkOrderId(workOrderInfo.getWorkOrderId());
        ipqcDto.setWorkOrderCode(workOrderInfo.getWorkOrderCode());
        ipqcDto.setWorkOrderName(workOrderInfo.getWorkOrderName());

        // 任务信息
        ipqcDto.setTaskId(task.getWorkOrderTaskId());
        ipqcDto.setTaskCode(taskInfo.getTaskCode());
        ipqcDto.setTaskName(taskInfo.getProcessName());

        // 工序信息
        ipqcDto.setProcessId(taskInfo.getProcessId());
        ipqcDto.setProcessCode(taskInfo.getProcessCode());
        ipqcDto.setProcessName(taskInfo.getProcessName());

        // 产品信息
        ipqcDto.setProductId(workOrderInfo.getProductId());
        ipqcDto.setProductCode(workOrderInfo.getProductCode());
        ipqcDto.setProductName(workOrderInfo.getProductName());
        ipqcDto.setProductSfn(workOrderInfo.getSpecification());
        ipqcDto.setUnit(workOrderInfo.getUnit());

        // 检测数量信息
        ipqcDto.setQuantityCheckNum(workReportDto.getGoodQty()); // 检测数量等于报工合格数量
        ipqcDto.setQuantityQualifiedNum(BigDecimal.ZERO); // 初始为0，等待检验
        ipqcDto.setQuantityUnqualifiedNum(BigDecimal.ZERO); // 初始为0，等待检验

        // 检测标准（从模板获取）
        ipqcDto.setCrRate(BigDecimal.valueOf(template.getCr_rate()));
        ipqcDto.setMajRate(BigDecimal.valueOf(template.getMaj_rate()));
        ipqcDto.setMinRate(BigDecimal.valueOf(template.getMin_rate()));

        // 状态信息
        ipqcDto.setCheckResult("3"); // 3=待检
        ipqcDto.setStatus("3"); // 1=报工检验
        ipqcDto.setInspectDate(new Date());
        ipqcDto.setInspector(SecurityUtils.getUsername());

        return ipqcDto;
    }

    /**
     * 记录质检异常信息
     * @param task 工序任务
     * @param workReportDto 报工数据
     * @param exceptionMessage 异常信息
     */
    private void recordQualityException(ScWorkOrderTask task, WorkReportDto workReportDto, String exceptionMessage) {
        try {
            System.out.println("=== 记录质检异常信息 ===");
            System.out.println("工序任务ID: " + task.getWorkOrderTaskId());
            System.out.println("异常信息: " + exceptionMessage);

            // 这里可以扩展为写入异常记录表，发送通知等
            // 目前先记录日志
            String logMessage = String.format(
                    "质检异常 - 工序任务[%s], 工单[%s], 报工数量[%s], 异常原因: %s",
                    task.getTaskCode(),
                    task.getWorkOrderId(),
                    workReportDto.getGoodQty(),
                    exceptionMessage
            );

            System.err.println(logMessage);

            // TODO: 可以在这里添加更多异常处理逻辑
            // 1. 写入异常记录表
            // 2. 发送异常通知
            // 3. 更新任务状态为异常状态
            // 4. 创建质检任务等

        } catch (Exception e) {
            System.err.println("记录质检异常信息失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 创建报工记录
     * @param dto 报工数据传输对象
     * @param task 工序任务对象
     * @return 创建的报工记录
     */
    private ScWorkReport createWorkReport(WorkReportDto dto, ScWorkOrderTask task) {
        ScWorkReport report = new ScWorkReport();
        report.setWorkOrderTaskId(dto.getWorkOrderTaskId());
        report.setWorkOrderId(task.getWorkOrderId());
        report.setReportCode(generateCode(22L));
        report.setWorkerId(SecurityUtils.getUserId());
        report.setQualifiedQty(dto.getGoodQty());
        report.setUnqualifiedQty(dto.getScrapQty());
        report.setReportTime(DateUtils.getNowDate());
        report.setStatus("0"); // 0-已报工
        report.setRemark(dto.getRemark());
        report.setCreateBy(SecurityUtils.getUsername());
        return report;
    }

    /**
     * 更新任务进度
     * @param dto 报工数据传输对象
     * @param task 工序任务对象
     */
    private void updateTaskProgress(WorkReportDto dto, ScWorkOrderTask task) {
        BigDecimal totalCompleted = task.getCompletedQty().add(dto.getGoodQty()).add(dto.getScrapQty());
        task.setCompletedQty(totalCompleted);
        task.setQualifiedQty(task.getQualifiedQty().add(dto.getGoodQty()));
        task.setUnqualifiedQty(task.getUnqualifiedQty().add(dto.getScrapQty()));

        // 判断任务是否完成
        String oldStatus = task.getStatus();
        if (totalCompleted.compareTo(task.getQtyNum()) >= 0) {
            // 判断是否需要质检
            boolean needsQualityCheck = isQualityCheckRequired(task);

            if (needsQualityCheck) {
                task.setStatus("5"); // 5-待质检（报工完成后先进入质检状态）
                System.out.println("任务需要质检，设置状态为待质检");
            } else {
                task.setStatus("3"); // 3-已完成（无需质检直接完成）
                System.out.println("任务无需质检，直接设置状态为已完成");
            }
            task.setActualEndTime(DateUtils.getNowDate());
        }
        task.setUpdateBy(SecurityUtils.getUsername());
        scWorkOrderTaskMapper.updateScWorkOrderTask(task);

        // 推送状态更新
        if (totalCompleted.compareTo(task.getQtyNum()) >= 0) {
            boolean needsQualityCheck = isQualityCheckRequired(task);
            String finalStatus = needsQualityCheck ? "5" : "3";
            String statusMessage = needsQualityCheck ? "报工完成，等待质检处理" : "报工完成，任务已完成";

            webSocketService.pushTaskStatusUpdate(
                    task.getWorkOrderTaskId(),
                    oldStatus,
                    finalStatus,
                    statusMessage
            );

            // 如果无需质检，直接处理入库和上级状态更新
            if (!needsQualityCheck) {
                handleTaskCompletionWithoutQC(task, dto);
            }
        }
    }

    /**
     * 创建退料记录
     * @param task 工序任务
     * @param workReportDto 报工数据
     */
    private void createMaterialReturnRecord(ScWorkOrderTask task, WorkReportDto workReportDto) {
        try {
            System.out.println("=== 创建退料记录 ===");

            // 1. 查询实际领料记录
            List<ScMaterialIssueDetail> actualIssueDetails = scMaterialIssueDetailMapper.selectIssueDetailsByTaskId(task.getWorkOrderTaskId());
            if (actualIssueDetails == null || actualIssueDetails.isEmpty()) {
                System.out.println("工序任务[" + task.getWorkOrderTaskId() + "]没有实际领料记录，跳过退料记录创建");
                return;
            }

            System.out.println("找到实际领料记录: " + actualIssueDetails.size() + " 条");

            // 2. 创建退料单头
            ScMaterialReturn materialReturn = new ScMaterialReturn();
            materialReturn.setReturnCode(generateCode(33L));
            materialReturn.setWorkOrderId(task.getWorkOrderId());
            materialReturn.setWorkOrderTaskId(task.getWorkOrderTaskId());
            materialReturn.setReturnDate(DateUtils.getNowDate());
            materialReturn.setWarehouseId(1L); // 默认仓库ID，可根据实际情况调整
            materialReturn.setStatus("0"); // 0=待审核
            materialReturn.setRemark("报工自动生成退料记录");
            materialReturn.setCreateBy(SecurityUtils.getUsername());
            materialReturn.setCreateTime(DateUtils.getNowDate());
            materialReturn.setIsDelete("0");

            int returnResult = scMaterialReturnMapper.insertScMaterialReturn(materialReturn);
            if (returnResult <= 0) {
                System.err.println("创建退料单头失败");
                return;
            }

            Long materialReturnId = materialReturn.getMaterialReturnId();
            System.out.println("成功创建退料单头，ID: " + materialReturnId + ", 编号: " + materialReturn.getReturnCode());

            // 3. 按物料汇总实际领料数量
            Map<Long, BigDecimal> materialIssueMap = new HashMap<>();
            for (ScMaterialIssueDetail detail : actualIssueDetails) {
                Long materialId = detail.getMaterialId();
                BigDecimal qty = detail.getQtyNum() != null ? detail.getQtyNum() : BigDecimal.ZERO;
                materialIssueMap.merge(materialId, qty, BigDecimal::add);
            }

            // 4. 创建退料明细
            List<ScMaterialReturnDetail> returnDetails = new ArrayList<>();
            for (Map.Entry<Long, BigDecimal> entry : materialIssueMap.entrySet()) {
                Long materialId = entry.getKey();
                BigDecimal actualIssueQty = entry.getValue();

                // 计算退料数量
                BigDecimal returnQuantity = calculateReturnQuantityForActualMaterial(task, materialId, actualIssueQty, workReportDto.getGoodQty());
                if (returnQuantity.compareTo(BigDecimal.ZERO) <= 0) {
                    System.out.println("物料ID[" + materialId + "]退料数量为0，跳过");
                    continue;
                }

                ScMaterialReturnDetail returnDetail = new ScMaterialReturnDetail();
                returnDetail.setMaterialReturnId(materialReturnId);
                returnDetail.setMaterialId(materialId);
                returnDetail.setQtyNum(returnQuantity);
                returnDetail.setRemark("报工自动生成");
                returnDetail.setCreateBy(SecurityUtils.getUsername());
                returnDetail.setCreateTime(DateUtils.getNowDate());
                returnDetail.setIsDelete("0");

                returnDetails.add(returnDetail);
            }

            // 5. 批量插入退料明细
            if (!returnDetails.isEmpty()) {
                int detailResult = scMaterialReturnDetailMapper.batchInsertScMaterialReturnDetail(returnDetails);
                if (detailResult > 0) {
                    System.out.println("成功创建 " + returnDetails.size() + " 条退料明细记录");
                } else {
                    System.err.println("批量创建退料明细失败");
                }
            } else {
                System.out.println("没有需要退料的物料");
            }

            System.out.println("=== 退料记录创建完成 ===");

        } catch (Exception e) {
            System.err.println("创建退料记录异常: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 直接创建退料入库记录（不需要质检）
     * @param task 工序任务
     * @param workReportDto 报工数据
     */
    private void createReturnInboundRecordDirectly(ScWorkOrderTask task, WorkReportDto workReportDto) {
        try {
            System.out.println("=== 直接创建退料入库记录 ===");

            // 1. 获取工单信息
            WorkOrderVO workOrder = scWorkOrderMapper.selectWorkOrderById(task.getWorkOrderId());
            if (workOrder == null) {
                System.err.println("找不到工单信息，ID: " + task.getWorkOrderId());
                return;
            }

            // 2. 根据产品ID查询BOM信息
            ScBomVo bomVo = scBomMapper.selectBomByProductId(workOrder.getProductId());
            if (bomVo == null) {
                System.out.println("产品[" + workOrder.getProductName() + "]没有配置BOM，无法创建退料入库记录");
                return;
            }

            // 3. 查询BOM明细列表
            List<ScBomDetailVo> bomDetails = scBomMapper.selectBomDetailListByBomId(bomVo.getBomId());
            if (bomDetails == null || bomDetails.isEmpty()) {
                System.out.println("BOM[" + bomVo.getBomCode() + "]没有明细数据，无法创建退料入库记录");
                return;
            }

            // 4. 创建统一退料入库记录
            boolean result = createMaterialReturnInboundRecord(
                    task.getWorkOrderTaskId(),
                    workOrder.getWorkOrderId(),
                    workOrder.getWorkOrderCode(),
                    bomDetails,
                    workReportDto.getGoodQty() != null ? workReportDto.getGoodQty() : BigDecimal.ZERO,
                    workReportDto.getScrapQty() != null ? workReportDto.getScrapQty() : BigDecimal.ZERO
            );

            if (result) {
                System.out.println("退料入库记录创建成功");
            } else {
                System.err.println("退料入库记录创建失败");
            }

        } catch (Exception e) {
            System.err.println("直接创建退料入库记录异常: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 报工时创建退料质检单（基于实际领料记录）
     * @param task 工序任务
     * @param workReportDto 报工数据
     */
    private void createReturnMaterialQcOrderOnReport(ScWorkOrderTask task, WorkReportDto workReportDto) {
        try {
            System.out.println("=== 报工时创建退料质检单（基于实际领料记录）===");

            // 1. 查询实际领料记录
            List<ScMaterialIssueDetail> actualIssueDetails = scMaterialIssueDetailMapper.selectIssueDetailsByTaskId(task.getWorkOrderTaskId());
            if (actualIssueDetails == null || actualIssueDetails.isEmpty()) {
                System.out.println("工序任务[" + task.getWorkOrderTaskId() + "]没有实际领料记录，跳过退料质检单创建");
                return;
            }

            System.out.println("找到实际领料记录: " + actualIssueDetails.size() + " 条");

            // 2. 按物料ID分组，合并同种物料的领料数量
            Map<Long, MaterialIssueInfo> materialIssueMap = new HashMap<>();
            for (ScMaterialIssueDetail detail : actualIssueDetails) {
                Long materialId = detail.getMaterialId();
                BigDecimal qtyNum = detail.getQtyNum();

                if (materialIssueMap.containsKey(materialId)) {
                    // 累加同种物料的数量
                    MaterialIssueInfo existingInfo = materialIssueMap.get(materialId);
                    existingInfo.setTotalQty(existingInfo.getTotalQty().add(qtyNum));
                } else {
                    // 创建新的物料信息
                    MaterialIssueInfo materialInfo = new MaterialIssueInfo();
                    materialInfo.setMaterialId(materialId);
                    materialInfo.setTotalQty(qtyNum);
                    materialInfo.setBatchNo(detail.getBatchNo());
                    materialInfo.setInventoryId(detail.getInventoryId());
                    materialIssueMap.put(materialId, materialInfo);
                }
            }

            // 3. 为每种实际领用的物料创建退料质检单
            for (Map.Entry<Long, MaterialIssueInfo> entry : materialIssueMap.entrySet()) {
                Long materialId = entry.getKey();
                MaterialIssueInfo materialInfo = entry.getValue();

                // 查询物料基本信息
                BasicWlgl materialDetail = getMaterialById(materialId);
                if (materialDetail == null) {
                    System.err.println("⚠️ 数据不一致警告：物料ID[" + materialId + "]在basic_wl表中不存在，但在领料记录中存在");
                    System.err.println("   建议检查数据完整性，跳过该物料的退料质检单创建");
                    continue;
                }

                // 计算退料数量（使用改进的计算逻辑）
                BigDecimal returnQuantity = calculateReturnQuantityForActualMaterial(task, materialId, materialInfo.getTotalQty(), workReportDto.getGoodQty());
                if (returnQuantity.compareTo(BigDecimal.ZERO) <= 0) {
                    System.out.println(String.format("物料[%s]退料数量为0，跳过质检单创建", materialDetail.getMaterial_name()));
                    continue;
                }

                // 创建退料质检单
                createReturnMaterialQcOrderForActualMaterial(task, materialDetail, materialInfo, returnQuantity);
            }

            System.out.println("报工时退料质检单创建完成");

        } catch (Exception e) {
            System.err.println("报工时创建退料质检单异常: " + e.getMessage());
            e.printStackTrace();
        }
    }


    /**
     * 为实际领用的物料创建退料质检单
     * @param task 工序任务
     * @param materialDetail 物料详细信息
     * @param materialInfo 物料领用信息
     * @param returnQuantity 退料数量
     */
    private void createReturnMaterialQcOrderForActualMaterial(ScWorkOrderTask task, BasicWlgl materialDetail,
                                                              MaterialIssueInfo materialInfo, BigDecimal returnQuantity) {
        try {
            // 1. 查询物料的检测方案
            QcTemplateProductDto template = null;
            try {
                template = detectService.selectQcTemplateProductMaterialCode(materialDetail.getMaterial_code());
                System.out.println(String.format("物料[%s]检测方案查询结果: %s",
                        materialDetail.getMaterial_name(), template != null ? "找到" : "未找到"));
            } catch (Exception e) {
                System.err.println(String.format("查询物料[%s]检测方案异常: %s",
                        materialDetail.getMaterial_name(), e.getMessage()));
                // 使用默认模板
                template = new QcTemplateProductDto();
                template.setTemplate_id(1L);
            }

            // 2. 创建退料检验单DTO
            QcRqcDto rqcDto = new QcRqcDto();

            // 基本信息
            String rqcCode = "RQC-REPORT-" + task.getTaskCode() + "-" + materialDetail.getMaterial_code() + "-" + System.currentTimeMillis();
            rqcDto.setRqcCode(rqcCode);
            rqcDto.setRqcName("报工退料检验-" + task.getTaskCode() + "-" + materialDetail.getMaterial_name());
            rqcDto.setRqcType("4"); // 4=退料检验

            // 模板信息
            rqcDto.setTemplateId(template.getTemplate_id() != null ? template.getTemplate_id() : 1L);

            // 来源单据信息 - 直接关联到工序任务
            rqcDto.setSourceDocId(task.getWorkOrderTaskId());
            rqcDto.setSourceDocType("1"); // 退料质检
            rqcDto.setSourceDocCode(task.getTaskCode());
            rqcDto.setSourceLineId(task.getWorkOrderTaskId());

            // 批次信息
            rqcDto.setBatchCode(materialInfo.getBatchNo() != null ? materialInfo.getBatchNo() :
                    "BATCH-" + task.getTaskCode() + "-" + materialDetail.getMaterial_code());

            // 物料信息
            rqcDto.setMaterialId(materialDetail.getMaterial_id()); // 修复：添加缺失的materialId
            rqcDto.setMaterialCode(materialDetail.getMaterial_code());
            rqcDto.setMaterialName(materialDetail.getMaterial_name());
            rqcDto.setMaterialSfn(materialDetail.getMaterial_sfn());
            rqcDto.setUnit(materialDetail.getMaterial_unit());

            // 检测数量
            rqcDto.setQuantityCheckNum(returnQuantity);
            rqcDto.setStatus("3"); // 3=待检
            rqcDto.setRemark(String.format("物料退料质检-%s", materialDetail.getMaterial_name()));

            // 3. 调用质检接口创建检验单
            AjaxResult result = detectService.add(rqcDto);
            if (result == null || !result.isSuccess()) {
                System.err.println("创建退料检验单失败: " + (result != null ? result.get("msg") : "返回为空"));
            } else {
                System.out.println("退料检验单创建成功: " + rqcCode + ", 物料: " + materialDetail.getMaterial_name());
            }

        } catch (Exception e) {
            System.err.println("为物料创建退料质检单异常: " + e.getMessage() + ", 物料: " + materialDetail.getMaterial_name());
            e.printStackTrace();
        }
    }


    /**
     * 判断任务是否需要质检
     * @param task 工序任务
     * @return true=需要质检，false=无需质检
     */
    private boolean isQualityCheckRequired(ScWorkOrderTask task) {
        try {
            // 1. 获取工序任务详细信息（包含产品信息）
            WorkOrderTaskDetailVO taskDetail = scWorkOrderTaskMapper.selectWorkOrderTaskDetailById(task.getWorkOrderTaskId());
            if (taskDetail == null || taskDetail.getWorkOrderInfo() == null) {
                System.out.println("无法获取工序任务详细信息，默认不需要质检");
                return false; // 无法获取信息时默认不需要质检
            }

            WorkOrderTaskDetailVO.WorkOrderInfo workOrderInfo = taskDetail.getWorkOrderInfo();

            // 2. 查询产品的检测方案
            QcTemplateProductDto template = null;
            if (workOrderInfo.getProductId() != null) {
                try {
                    template = detectService.selectQcTemplateProductProductCode(workOrderInfo.getProductId());
                    System.out.println("产品检测方案查询结果: " + (template != null ? "找到，需要质检" : "未找到，无需质检"));
                } catch (Exception e) {
                    System.err.println("查询产品检测方案异常: " + e.getMessage());
                    return false; // 查询异常时默认不需要质检
                }
            }

            // 3. 根据检测方案判断是否需要质检
            return template != null;

        } catch (Exception e) {
            System.err.println("判断质检需求异常: " + e.getMessage());
            e.printStackTrace();
            return false; // 异常情况默认不需要质检
        }
    }

    /**
     * 处理无需质检的任务完成逻辑
     * @param task 工序任务
     * @param workReportDto 报工数据
     */
    private void handleTaskCompletionWithoutQC(ScWorkOrderTask task, WorkReportDto workReportDto) {
        try {
            System.out.println("=== 处理无需质检的任务完成 ===");
            System.out.println("任务ID: " + task.getWorkOrderTaskId());
            System.out.println("合格数量: " + workReportDto.getGoodQty());

            // 1. 处理库存（产品入库）
            updateInventory(task, workReportDto.getGoodQty(), true); // 无需质检默认合格

            // 2. 推送入库完成消息
            webSocketService.pushInboundComplete(
                    task.getWorkOrderTaskId(),
                    null,
                    workReportDto.getGoodQty().toString(),
                    "产品入库完成（无需质检）"
            );

            // 3. 检查并更新上级状态
            checkAndCompleteParentStatus(task);

            System.out.println("无需质检的任务完成处理成功");

        } catch (Exception e) {
            System.err.println("处理无需质检的任务完成异常: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 更新库存
     * @param task 工序任务对象
     * @param quantity 入库数量
     * @param isQualified 质检是否合格
     */
    private void updateInventory(ScWorkOrderTask task, BigDecimal quantity, boolean isQualified) {
        System.out.println("=== 开始库存更新 ===");
        System.out.println("工序任务ID: " + task.getWorkOrderTaskId());
        System.out.println("报工数量: " + quantity);

        if (quantity.compareTo(BigDecimal.ZERO) <= 0) {
            System.out.println("报工数量为0或负数，跳过库存更新");
            return;
        }
        // 获取工单信息，拿到产品ID
        WorkOrderVO workOrder = scWorkOrderMapper.selectWorkOrderById(task.getWorkOrderId());
        if (workOrder == null || workOrder.getProductId() == null) {
            throw new ServiceException("无法找到工单或工单缺少产品信息");
        }

        // 创建生产入库记录
        System.out.println("=== 开始创建生产入库记录 ===");
        boolean inboundResult = createProductionInboundRecord(task, workOrder, quantity, isQualified);
        if (!inboundResult) {
            System.err.println("生产入库记录创建失败，但不影响库存更新");
        } else {
            System.out.println("生产入库记录创建成功");
        }

        // 注释：自动退料逻辑已移至报工时创建，此处只处理产品入库
        System.out.println("=== 生产质检完成，只处理产品入库 ===");

        System.out.println("=== 库存更新完成 ===");
    }
    /**
     * 创建生产入库记录
     * @param task 工序任务对象
     * @param workOrder 工单信息
     * @param quantity 入库数量
     * @param isQualified 质检是否合格
     * @return 操作结果，true=成功，false=失败
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean createProductionInboundRecord(ScWorkOrderTask task, WorkOrderVO workOrder, BigDecimal quantity, boolean isQualified) {
        try {
            String username = SecurityUtils.getUsername();
            Date currentDate = DateUtils.getNowDate();
            Date expireDate = DateUtils.addDays(currentDate, 3);

            // 1. 查询工单详细信息获取批次号
            ScWorkOrder workOrderDetail = scWorkOrderMapper.selectScWorkOrderById(workOrder.getWorkOrderId());
            System.out.println("=== 工单批次号检查 ===");
            System.out.println("工单ID: " + workOrder.getWorkOrderId());
            System.out.println("工单编号: " + workOrder.getWorkOrderCode());
            if (workOrderDetail != null) {
                System.out.println("工单详情查询成功");
                System.out.println("工单中的批次号: " + workOrderDetail.getBatchNumber());
            } else {
                System.out.println("工单详情查询失败，workOrderDetail为null");
            }

            String lotNumber = workOrderDetail != null && workOrderDetail.getBatchNumber() != null ?
                    workOrderDetail.getBatchNumber() : workOrder.getWorkOrderCode() + "-LOT";
            System.out.println("最终使用的生产批号: " + lotNumber);

            // 2. 创建新的批次记录
            System.out.println("=== 创建新的批次记录 ===");

            CkBatch batch = new CkBatch();
            batch.setProduce_date(currentDate);
            batch.setRecpt_date(currentDate);
            batch.setWork_order_id(workOrder.getWorkOrderId());
            batch.setWork_order_code(workOrder.getWorkOrderCode());
            batch.setWork_order_name(workOrder.getWorkOrderName());
            batch.setLot_number(lotNumber);
            batch.setQuality_status("1"); // 1=合格
            batch.setRemark("生产报工自动生成");
            batch.setCreate_by(username);
            batch.setUpdate_by(username);
            batch.setCreate_time(currentDate);
            batch.setUpdate_time(currentDate);
            batch.setBatch_code(generateCode(28L));
            batch.setIs_delete("0");
            // 调用新增批次方法，直接返回批次对象
            UR batchResult = inventoryService.addBatch(batch);
            if (!batchResult.isFlag()) {
                throw new ServiceException("创建批次失败: " + batchResult.getMsg());
            }

            // 使用已创建批次的编码
            String batchCode = batch.getBatch_code();

            if (batchCode == null || batchCode.isEmpty()) {
                throw new ServiceException("创建批次失败，批次编号为空");
            }

            System.out.println("成功创建批次，批次编号: " + batchCode);

            // 2. 创建入库单表头
            String recptCode = generateCode(29L);
            String recptName = "生产入库-" + workOrder.getWorkOrderCode();

            // 根据质检结果设置入库状态
            String inboundStatus;
            if (isQualified) {
                inboundStatus = "3"; // 3=合格
                System.out.println("质检合格，设置入库状态为合格");
            } else {
                inboundStatus = "2"; // 2=待质检
                System.out.println("质检不合格或待检，设置入库状态为待质检");
            }

            CkItemRecpt recpt = new CkItemRecpt(
                    null, // iqcId 由数据库自动生成
                    recptCode, // iqcCode - 入库单编号
                    recptCode, // recptCode - 入库单编号
                    recptName, // recptName - 入库单名称
                    recptName, // iqcName - 来料检验单名称
                    null, // poId 采购订单编号ID
                    null, // poCode 采购订单编号
                    null, // poName 采购订单名称
                    batchCode, // batchCode 批次编号
                    null, // supplierId 供应商ID
                    null, // supplierName 供应商名称
                    workOrder.getWorkOrderId(),
                    workOrder.getWorkOrderCode(),
                    workOrder.getWorkOrderName(),
                    inboundStatus, // 3=生产入库
                    224L, // 成品仓库ID
                    "成品仓", // 成品仓库名称
                    currentDate,
                    "3", // 根据质检结果设置状态
                    "生产报工自动生成",
                    task.getWorkOrderTaskId().toString(), //给老熊预留一个工序任务ID
                    null, // attr2 预留字段2
                    null, // attr3 预留字段3
                    null, // attr4 预留字段4
                    "0"
            );
            recpt.setCreateBy(username);
            recpt.setUpdateBy(username);

            // 插入入库单表头并检查结果
            int recptResult = ckItemRecptMapper.insertCkItemRecpt(recpt);
            if (recptResult <= 0) {
                throw new ServiceException("创建入库单表头失败");
            }

            // 3. 创建入库单明细
            // 根据质检结果设置质检标识
            String iqcCheckFlag = isQualified ? "0" : "1"; // 0=无需质检，1=需要质检

            CkItemRecptLine recptLine = new CkItemRecptLine(
                    null, // lineId 由数据库自动生成
                    recpt.getIqcId(),
                    null, // orderLineId 采购订单行ID
                    workOrder.getProductCode(),
                    workOrder.getProductName(),
                    workOrder.getSpecification(), // specification 产品规格型号
                    workOrder.getUnit(),
                    quantity,
                    batchCode, // 使用创建的批次编号
                    251L, // 成品A区ID
                    "成品A区", // 成品A区名称
                    352L, // 成品A区一号位ID
                    "成品A区一号位", // 成品A区一号位名称
                    currentDate,
                    expireDate, // expireDate 有效期
                    lotNumber, // 使用实际的生产批号
                    iqcCheckFlag, // 根据质检结果设置质检标识
                    null, // qcId 质检ID
                    "生产报工自动生成",
                    null, // attr1 预留字段1
                    null, // attr2 预留字段2
                    "2",
                    null, // attr3 预留字段3
                    null  // attr4 预留字段4
            );
            recptLine.setCreateBy(username);
            recptLine.setUpdateBy(username);

            // 插入入库单明细并检查结果
            int lineResult = ckItemRecptLineMapper.insertCkItemRecptLine(recptLine);
            if (lineResult <= 0) {
                throw new ServiceException("创建入库单明细失败");
            }

            return true;
        } catch (Exception e) {
            // 记录日志并抛出异常以触发事务回滚
            System.err.println("创建生产入库记录失败: " + e.getMessage());
            e.printStackTrace();
            throw new ServiceException("创建生产入库记录失败: " + e.getMessage());
        }
    }

    /**
     * 检查并更新上级工单状态
     * @param task 工序任务对象
     */
    private void checkAndCompleteParentStatus(ScWorkOrderTask task) {
        // 如果任务未完成，则无需更新上级状态
        if (!"3".equals(task.getStatus())) {
            return;
        }

        // 检查同一工单下的所有任务是否都已完成
        long unfinishedTasks = scWorkOrderTaskMapper.countUnfinishedTasksByWorkOrderId(task.getWorkOrderId());
        if (unfinishedTasks == 0) {
            // 所有任务完成，更新工单状态
            ScWorkOrder workOrder = new ScWorkOrder();
            workOrder.setWorkOrderId(task.getWorkOrderId());
            workOrder.setStatus("3"); // 3-已完成
            workOrder.setUpdateBy(SecurityUtils.getUsername());
            scWorkOrderMapper.updateScWorkOrder(workOrder);

            // 递归检查上级（生产计划、生产订单）
            checkAndCompletePlanAndOrderStatus(task.getWorkOrderId());
        }
    }

    /**
     * 检查并更新生产计划和生产订单状态
     * @param workOrderId 工单ID
     */
    private void checkAndCompletePlanAndOrderStatus(Long workOrderId) {
        ScWorkOrder workOrder = scWorkOrderMapper.selectScWorkOrderById(workOrderId);
        if (workOrder == null || workOrder.getProductionPlanId() == null) {
            return;
        }

        // 严格检查同一生产计划下的所有工单是否都已完成
        boolean allWorkOrdersCompleted = scWorkOrderMapper.checkAllWorkOrdersCompleted(workOrder.getProductionPlanId());

        if (allWorkOrdersCompleted) {
            System.out.println("生产计划下所有工单已完成，更新生产计划状态为已完成，计划ID: " + workOrder.getProductionPlanId());

            // 更新生产计划状态为已完成
            scProductionPlanMapper.updateStatusToComplete(workOrder.getProductionPlanId(), SecurityUtils.getUsername());

            Long productionOrderId = scProductionPlanMapper.getProductionOrderIdByPlanId(workOrder.getProductionPlanId());
            if (productionOrderId != null) {
                // 检查同一生产订单下的所有生产计划是否完成
                long unfinishedPlans = scProductionPlanMapper.countUnfinishedPlansByOrderId(productionOrderId);
                if (unfinishedPlans == 0) {
                    System.out.println("生产订单下所有生产计划已完成，更新生产订单状态为已完成，订单ID: " + productionOrderId);
                    // 更新生产订单状态为已完成
                    scProductionOrderMapper.updateStatusToComplete(productionOrderId, SecurityUtils.getUsername());
                }
            }
        } else {
            // 获取工单状态详情用于调试
            List<String> workOrderStatuses = scWorkOrderMapper.selectWorkOrderStatusByPlanId(workOrder.getProductionPlanId());
            System.out.println("生产计划下还有工单未完成，计划ID: " + workOrder.getProductionPlanId() + ", 工单状态: " + workOrderStatuses);
        }
    }


    /**
     * 远程调用基础服务生成编码，并健壮地处理返回结果。
     * @param type 编码类型
     * @return 生成的编码字符串
     */
    private String generateCode(Long type) {
        // 调用远程服务（消费模式，确保每次调用都会递增流水号）
        AjaxResult codeResult = basicService.automaticallyNumbersConsume(type);

        // 确保远程调用返回了结果对象
        if (codeResult == null) {
            throw new ServiceException(String.format("远程获取编码调用失败，返回结果为空，类型: %d", type));
        }

        // 根据该接口的特殊设计，编码直接存放在msg字段
        Object msg = codeResult.get(AjaxResult.MSG_TAG);
        Object code=codeResult.get(AjaxResult.CODE_TAG);
        System.out.println("编码是："+code);
        // 确保编码内容不为空
        if (msg == null || msg.toString().isEmpty()) {
            throw new ServiceException(String.format("远程获取编码成功，但返回的编码为空，类型: %d, 返回信息: %s", type, msg));
        }

        // 从AjaxResult中正确取出msg部分作为编码
        return msg.toString();
    }



    /**
     * 创建物料退料入库记录（统一入库单，包含所有物料的合格和不合格数量）
     * @param workOrderTaskId 工序任务ID
     * @param workOrderId 工单ID
     * @param workOrderCode 工单编号
     * @param bomDetails BOM明细列表（已废弃，保留参数兼容性）
     * @param qualifiedQty 合格数量
     * @param unqualifiedQty 不合格数量
     * @return 操作结果，true=成功，false=失败
     */
    private boolean createMaterialReturnInboundRecord(Long workOrderTaskId, Long workOrderId, String workOrderCode, List<ScBomDetailVo> bomDetails, BigDecimal qualifiedQty, BigDecimal unqualifiedQty) {
        try {
            String username = SecurityUtils.getUsername();
            Date currentDate = DateUtils.getNowDate();
            Date expireDate = DateUtils.addDays(currentDate, 3);

            // 1. 查询工单详细信息获取生产批号
            ScWorkOrder workOrderDetail = scWorkOrderMapper.selectScWorkOrderById(workOrderId);
            String lotNumber = workOrderDetail != null && workOrderDetail.getBatchNumber() != null ?
                    workOrderDetail.getBatchNumber() : workOrderCode + "-AUTO-LOT";

            System.out.println("=== 开始创建统一退料入库记录 ===");
            System.out.println("工序任务ID: " + workOrderTaskId);
            System.out.println("工单ID: " + workOrderId);
            System.out.println("工单编号: " + workOrderCode);
            System.out.println("合格数量: " + qualifiedQty);
            System.out.println("不合格数量: " + unqualifiedQty);

            // 2. 查询该工序任务的实际领料记录
            List<ScMaterialIssueDetail> actualIssueDetails = scMaterialIssueDetailMapper.selectIssueDetailsByTaskId(workOrderTaskId);
            if (actualIssueDetails == null || actualIssueDetails.isEmpty()) {
                System.out.println("工序任务[" + workOrderTaskId + "]没有找到实际领料记录，无法创建退料入库记录");
                return false;
            }

            System.out.println("=== 找到实际领料记录: " + actualIssueDetails.size() + " 条 ===");
            for (ScMaterialIssueDetail detail : actualIssueDetails) {
                System.out.println(String.format("领料明细: 物料ID=%s, 数量=%s, 批次=%s, 库存ID=%s",
                        detail.getMaterialId(), detail.getQtyNum(), detail.getBatchNo(), detail.getInventoryId()));
            }

            System.out.println("找到实际领料记录: " + actualIssueDetails.size() + " 条");

            // 按物料ID分组，合并同种物料的领料数量
            Map<Long, MaterialIssueInfo> materialIssueMap = new HashMap<>();
            for (ScMaterialIssueDetail detail : actualIssueDetails) {
                Long materialId = detail.getMaterialId();
                BigDecimal qtyNum = detail.getQtyNum();

                System.out.println(String.format("处理领料记录: 物料ID=%s, 数量=%s, 批次=%s",
                        materialId, qtyNum, detail.getBatchNo()));

                if (materialIssueMap.containsKey(materialId)) {
                    // 累加同种物料的数量
                    MaterialIssueInfo existingInfo = materialIssueMap.get(materialId);
                    BigDecimal oldQty = existingInfo.getTotalQty();
                    existingInfo.setTotalQty(oldQty.add(qtyNum));
                    System.out.println(String.format("  累加物料数量: %s + %s = %s", oldQty, qtyNum, existingInfo.getTotalQty()));
                } else {
                    // 创建新的物料信息
                    MaterialIssueInfo materialInfo = new MaterialIssueInfo();
                    materialInfo.setMaterialId(materialId);
                    materialInfo.setTotalQty(qtyNum);
                    materialInfo.setBatchNo(detail.getBatchNo());
                    materialInfo.setInventoryId(detail.getInventoryId());
                    materialIssueMap.put(materialId, materialInfo);
                    System.out.println(String.format("  新增物料: ID=%s, 数量=%s", materialId, qtyNum));
                }
            }

            System.out.println(String.format("工序任务[%s]实际领用了%d种物料，开始创建统一退料入库单",
                    workOrderTaskId, materialIssueMap.size()));

            // 3. 创建批次记录
            // 使用已有的lotNumber变量

            CkBatch batch = new CkBatch();
            batch.setProduce_date(currentDate);
            batch.setRecpt_date(currentDate);
            batch.setWork_order_id(workOrderId);
            batch.setWork_order_code(workOrderCode);
            batch.setWork_order_name(String.format("退料入库-%s", workOrderCode));
            batch.setLot_number(lotNumber);
            batch.setQuality_status("2"); // 2=待质检（退料需要重新质检）
            batch.setRemark(String.format("工序任务[%s]退料入库自动生成", workOrderTaskId));
            batch.setCreate_by(username);
            batch.setUpdate_by(username);
            batch.setCreate_time(currentDate);
            batch.setUpdate_time(currentDate);
            batch.setBatch_code(generateCode(28L));
            batch.setIs_delete("0");

            // 调用新增批次方法
            UR batchResult = inventoryService.addBatch(batch);
            if (!batchResult.isFlag()) {
                throw new ServiceException("创建退料入库批次失败: " + batchResult.getMsg());
            }

            System.out.println("成功创建退料入库批次，批次编号: " + batch.getBatch_code());

            // 4. 创建统一的入库单表头
            String recptCode = generateCode(29L);
            String recptName = String.format("退料入库-%s", workOrderCode);

            CkItemRecpt recpt = new CkItemRecpt(
                    null, // iqcId 由数据库自动生成
                    recptCode, // iqcCode - 入库单编号
                    recptCode, // recptCode - 入库单编号
                    recptName, // recptName - 入库单名称
                    recptName, // iqcName - 来料检验单名称
                    null, // poId 采购订单ID
                    null, // poCode 采购订单编号
                    null, // poName 采购订单名称
                    batch.getBatch_code(), // batchCode 使用已创建的批次编号
                    null, // supplierId 供应商ID
                    null, // supplierName 供应商名称
                    workOrderId, // workOrderId 生产工单ID
                    workOrderCode, // workOrderCode 生产工单编号
                    String.format("退料入库-%s", workOrderCode), // workOrderName 生产工单名称
                    "2", // storageType 入库类型：2=退料入库
                    223L, // warehouseId 物料仓库ID
                    "物料仓", // warehouseName 物料仓库名称
                    currentDate, // recptDate 入库日期
                    "2", // status 状态：2=待质检
                    String.format("工序任务[%s]退料入库", workOrderTaskId), // remark 备注
                    null, // attr1 预留字段1
                    null, // attr2 预留字段2
                    null, // attr3 预留字段3
                    null, // attr4 预留字段4
                    "0" // isDelete 删除标记
            );
            recpt.setCreateBy(username);
            recpt.setUpdateBy(username);

            // 插入入库单表头
            int recptResult = ckItemRecptMapper.insertCkItemRecpt(recpt);
            if (recptResult <= 0) {
                throw new ServiceException("创建退料入库单表头失败");
            }

            System.out.println("统一入库单表头创建成功，入库单号: " + recptCode);

            // 4. 为每种物料创建入库明细（合格和不合格分别创建）
            List<CkItemRecptLine> recptLines = new ArrayList<>();
            for (Map.Entry<Long, MaterialIssueInfo> entry : materialIssueMap.entrySet()) {
                Long materialId = entry.getKey();
                MaterialIssueInfo materialInfo = entry.getValue();

                // 查询物料基本信息
                BasicWlgl materialDetail = getMaterialById(materialId);
                if (materialDetail == null) {
                    System.err.println("物料ID[" + materialId + "]不存在，跳过明细创建");
                    continue;
                }

                // 计算该物料的退料数量
                BigDecimal returnQuantity = materialInfo.getTotalQty();
                if (returnQuantity.compareTo(BigDecimal.ZERO) <= 0) {
                    System.out.println(String.format("物料[%s]退料数量为0，跳过", materialDetail.getMaterial_name()));
                    continue;
                }

                // 计算该物料的合格和不合格数量（按比例分配）
                BigDecimal totalQty = qualifiedQty.add(unqualifiedQty != null ? unqualifiedQty : BigDecimal.ZERO);
                BigDecimal materialQualifiedQty = BigDecimal.ZERO;
                BigDecimal materialUnqualifiedQty = BigDecimal.ZERO;

                if (totalQty.compareTo(BigDecimal.ZERO) > 0) {
                    // 按比例计算该物料的合格和不合格数量
                    BigDecimal qualifiedRatio = qualifiedQty.divide(totalQty, 6, RoundingMode.HALF_UP);
                    BigDecimal unqualifiedRatio = unqualifiedQty != null ?
                            unqualifiedQty.divide(totalQty, 6, RoundingMode.HALF_UP) : BigDecimal.ZERO;

                    materialQualifiedQty = returnQuantity.multiply(qualifiedRatio);
                    materialUnqualifiedQty = returnQuantity.multiply(unqualifiedRatio);
                }

                System.out.println(String.format("物料[%s] - 总退料数量: %s, 合格数量: %s, 不合格数量: %s",
                        materialDetail.getMaterial_name(), returnQuantity, materialQualifiedQty, materialUnqualifiedQty));

                // 创建合格数量的明细行
                if (materialQualifiedQty.compareTo(BigDecimal.ZERO) > 0) {
                    CkItemRecptLine qualifiedLine = createRecptLine(recpt.getIqcId(), materialDetail,
                            materialQualifiedQty, "1", "合格", currentDate, expireDate, lotNumber, batch.getBatch_code(), username);
                    recptLines.add(qualifiedLine);
                }

                // 创建不合格数量的明细行
                if (materialUnqualifiedQty.compareTo(BigDecimal.ZERO) > 0) {
                    CkItemRecptLine unqualifiedLine = createRecptLine(recpt.getIqcId(), materialDetail,
                            materialUnqualifiedQty, "2", "不合格", currentDate, expireDate, lotNumber, batch.getBatch_code(), username);
                    recptLines.add(unqualifiedLine);
                }
            }

            // 5. 批量插入入库明细
            if (!recptLines.isEmpty()) {
                int lineResult = ckItemRecptLineMapper.batchInsertCkItemRecptLines(recptLines);
                if (lineResult <= 0) {
                    throw new ServiceException("批量创建退料入库单明细失败");
                }
                System.out.println("成功创建 " + recptLines.size() + " 条入库明细记录");
            }

            System.out.println("=== 统一退料入库记录创建完成 ===");

            return true;

        } catch (Exception e) {
            System.err.println("创建物料退料入库记录失败: " + e.getMessage());
            e.printStackTrace();
            throw new ServiceException("创建物料退料入库记录失败: " + e.getMessage());
        }
    }

    /**
     * 创建入库单明细行
     * @param recptId 入库单ID
     * @param materialDetail 物料详情
     * @param quantity 数量
     * @param status 状态（1=合格，2=不合格）
     * @param statusDesc 状态描述
     * @param currentDate 当前日期
     * @param expireDate 有效期
     * @param lotNumber 生产批号
     * @param batchCode 批次编号
     * @param username 用户名
     * @return 入库单明细行
     */
    private CkItemRecptLine createRecptLine(Long recptId, BasicWlgl materialDetail, BigDecimal quantity,
                                            String status, String statusDesc, Date currentDate, Date expireDate,
                                            String lotNumber, String batchCode, String username) {
        CkItemRecptLine recptLine = new CkItemRecptLine(
                null, // lineId 由数据库自动生成
                recptId, // recptId 入库单ID
                null, // orderLineId 采购订单行ID
                materialDetail.getMaterial_code(), // goodsCode 物料编码
                materialDetail.getMaterial_name(), // goodsName 物料名称
                materialDetail.getMaterial_sfn(), // specification 物料规格型号
                materialDetail.getMaterial_unit(), // unitName 单位名称
                quantity, // recivedNum 入库数量
                batchCode, // batchCode 使用传入的批次编号
                254L, // locationId 物料A区ID
                "物料A区", // locationName 物料A区名称
                359L, // areaId 物料A区一号位ID
                "物料A区一号位", // areaName 物料A区一号位名称
                currentDate, // produceDate 生产日期
                expireDate, // expireDate 有效期
                lotNumber, // 使用实际的生产批号
                "1", // iqcCheck 1=需要质检
                null, // qcId 质检ID
                String.format("退料入库-%s-%s", materialDetail.getMaterial_name(), statusDesc), // remark 备注
                null, // attr1 预留字段1
                null, // attr2 预留字段2
                "1",
                null, // attr3 预留字段3
                null  // attr4 预留字段4
        );
        recptLine.setCreateBy(username);
        recptLine.setUpdateBy(username);

        // 设置状态字段
        if ("1".equals(status)) {
            // 合格状态的处理逻辑
            recptLine.setRemark(recptLine.getRemark() + " [合格]");
        } else if ("2".equals(status)) {
            // 不合格状态的处理逻辑
            recptLine.setRemark(recptLine.getRemark() + " [不合格]");
        }

        return recptLine;
    }

    /**
     * 为实际领料物料计算退料数量（基于原有calculateReturnQuantity逻辑）
     * @param task 工序任务
     * @param materialId 物料ID
     * @param actualIssueQty 实际领料数量
     * @param reportedQty 报工数量
     * @return 退料数量
     */
    private BigDecimal calculateReturnQuantityForActualMaterial(ScWorkOrderTask task, Long materialId,
                                                                BigDecimal actualIssueQty, BigDecimal reportedQty) {
        try {
            System.out.println(String.format("=== 计算物料退料数量 ==="));
            System.out.println(String.format("工序任务ID: %s, 物料ID: %s, 实际领料: %s, 报工数量: %s",
                    task.getWorkOrderTaskId(), materialId, actualIssueQty, reportedQty));

            if (actualIssueQty == null || actualIssueQty.compareTo(BigDecimal.ZERO) <= 0) {
                System.out.println("实际领料数量为0，退料数量为0");
                return BigDecimal.ZERO;
            }

            if (reportedQty == null || reportedQty.compareTo(BigDecimal.ZERO) <= 0) {
                System.out.println("报工数量为0，退料数量为0");
                return BigDecimal.ZERO;
            }

            // 使用与原calculateReturnQuantity相同的逻辑：
            // 退料数量 = 实际领料数量 × (报工数量 / 计划生产数量)
            BigDecimal planQty = task.getQtyNum() != null ? task.getQtyNum() : BigDecimal.ONE;
            BigDecimal returnRatio = reportedQty.divide(planQty, 6, RoundingMode.HALF_UP);
            BigDecimal returnQuantity = actualIssueQty.multiply(returnRatio);

            System.out.println(String.format("退料数量计算 - 实际领料: %s, 报工数量: %s, 计划数量: %s, 退料比例: %s, 退料数量: %s",
                    actualIssueQty, reportedQty, planQty, returnRatio, returnQuantity));

            return returnQuantity;

        } catch (Exception e) {
            System.err.println("计算退料数量异常: " + e.getMessage() + ", 物料ID: " + materialId);
            e.printStackTrace();
            return BigDecimal.ZERO;
        }
    }



    /**
     * 根据物料ID查询物料信息
     * @param materialId 物料ID
     * @return 物料信息
     */
    private BasicWlgl getMaterialById(Long materialId) {
        try {
            System.out.println("开始查询物料ID: " + materialId);

            // 创建查询条件，设置大的分页参数以获取更多记录
            BasicWlgl queryCondition = new BasicWlgl();
            queryCondition.setMaterial_id(materialId);

            // 设置分页参数，确保能查询到足够多的记录
            Map<String, Object> params = new HashMap<>();
            params.put("pageNum", 1);
            params.put("pageSize", 1000); // 设置较大的页面大小
            queryCondition.setParams(params);

            // 调用BasicService查询物料列表
            TableDataInfo result = basicService.list(queryCondition);
            System.out.println("物料查询结果: " + (result != null ? "有结果" : "无结果"));

            if (result != null && result.getRows() != null && !result.getRows().isEmpty()) {
                System.out.println("找到物料记录数: " + result.getRows().size());

                // 在所有结果中查找目标物料ID
                for (Object row : result.getRows()) {
                    BasicWlgl material = null;

                    if (row instanceof BasicWlgl) {
                        material = (BasicWlgl) row;
                    } else if (row instanceof java.util.Map) {
                        material = convertMapToBasicWlgl((Map<String, Object>) row);
                    }

                    if (material != null && materialId.equals(material.getMaterial_id())) {
                        System.out.println(String.format("在结果列表中找到目标物料: ID=%s, 编码=%s, 名称=%s, is_detele=%s",
                                material.getMaterial_id(), material.getMaterial_code(), material.getMaterial_name(), material.getIs_detele()));
                        return material;
                    }
                }

                // 如果没找到，输出调试信息
                System.out.println("查询到的所有物料ID:");
                for (Object row : result.getRows()) {
                    if (row instanceof java.util.Map) {
                        Map<String, Object> map = (Map<String, Object>) row;
                        System.out.println("  - 物料ID: " + map.get("material_id") + ", 物料名称: " + map.get("material_name"));
                    } else if (row instanceof BasicWlgl) {
                        BasicWlgl material = (BasicWlgl) row;
                        System.out.println("  - 物料ID: " + material.getMaterial_id() + ", 物料名称: " + material.getMaterial_name());
                    }
                }

                System.err.println(String.format("在%d条记录中未找到物料ID=%s", result.getRows().size(), materialId));
            }

            System.err.println("未找到物料ID[" + materialId + "]的信息");
            return null;

        } catch (Exception e) {
            System.err.println("查询物料ID[" + materialId + "]信息失败: " + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将Map对象转换为BasicWlgl对象
     * @param materialMap Map对象
     * @return BasicWlgl对象
     */
    private BasicWlgl convertMapToBasicWlgl(java.util.Map<String, Object> materialMap) {
        try {
            BasicWlgl material = new BasicWlgl();

            // 设置物料ID
            Object materialIdObj = materialMap.get("material_id");
            if (materialIdObj instanceof Number) {
                material.setMaterial_id(((Number) materialIdObj).longValue());
            } else if (materialIdObj instanceof String) {
                material.setMaterial_id(Long.parseLong((String) materialIdObj));
            }

            // 设置其他属性
            if (materialMap.get("material_code") != null) {
                material.setMaterial_code(materialMap.get("material_code").toString());
            }
            if (materialMap.get("material_name") != null) {
                material.setMaterial_name(materialMap.get("material_name").toString());
            }
            if (materialMap.get("material_sfn") != null) {
                material.setMaterial_sfn(materialMap.get("material_sfn").toString());
            }
            if (materialMap.get("material_unit") != null) {
                material.setMaterial_unit(materialMap.get("material_unit").toString());
            }
            if (materialMap.get("is_detele") != null) {
                material.setIs_detele(materialMap.get("is_detele").toString());
            }

            return material;

        } catch (Exception e) {
            System.err.println("Map转换BasicWlgl失败: " + e.getMessage());
            return null;
        }
    }




    /**
     * 物料领料信息内部类
     */
    private static class MaterialIssueInfo {
        private Long materialId;
        private BigDecimal totalQty = BigDecimal.ZERO;
        private String batchNo;
        private Long inventoryId;

        // getter和setter方法
        public Long getMaterialId() { return materialId; }
        public void setMaterialId(Long materialId) { this.materialId = materialId; }
        public BigDecimal getTotalQty() { return totalQty; }
        public void setTotalQty(BigDecimal totalQty) { this.totalQty = totalQty; }
        public String getBatchNo() { return batchNo; }
        public void setBatchNo(String batchNo) { this.batchNo = batchNo; }
        public Long getInventoryId() { return inventoryId; }
        public void setInventoryId(Long inventoryId) { this.inventoryId = inventoryId; }
    }






    /**
     * 处理质检结果
     * @param task 工序任务
     * @param workReportDto 报工数据
     * @param isQualified 质检是否合格
     */
    public void handleQualityCheckResult(ScWorkOrderTask task, WorkReportDto workReportDto, boolean isQualified) {
        try {
            System.out.println("=== 处理质检结果 ===");
            System.out.println("任务ID: " + task.getWorkOrderTaskId());
            System.out.println("质检结果: " + (isQualified ? "合格" : "不合格"));

            // 1. 推送质检完成消息
            webSocketService.pushQualityCheckComplete(
                    task.getWorkOrderTaskId(),
                    null,
                    isQualified ? "1" : "2",
                    "质检完成，结果: " + (isQualified ? "合格" : "不合格")
            );

            // 2. 根据质检结果处理库存
            updateInventory(task, workReportDto.getGoodQty(), isQualified);

            // 3. 更新任务最终状态
            String finalStatus = isQualified ? "3" : "4"; // 3=已完成，4=已暂停（质检不合格）
            task.setStatus(finalStatus);
            task.setUpdateBy(SecurityUtils.getUsername());
            scWorkOrderTaskMapper.updateScWorkOrderTask(task);

            // 4. 推送最终状态更新
            webSocketService.pushTaskStatusUpdate(
                    task.getWorkOrderTaskId(),
                    "5",
                    finalStatus,
                    isQualified ? "质检合格，任务完成" : "质检不合格，任务暂停"
            );

            // 5. 推送入库完成消息
            if (isQualified) {
                webSocketService.pushInboundComplete(
                        task.getWorkOrderTaskId(),
                        null,
                        workReportDto.getGoodQty().toString(),
                        "产品入库完成"
                );

                // 6. 检查并更新上级状态（只有合格时才更新）
                checkAndCompleteParentStatus(task);
            } else {
                // 记录质检异常信息
                recordQualityException(task, workReportDto, "质检不合格，产品暂不可用");
            }

        } catch (Exception e) {
            System.err.println("处理质检结果异常: " + e.getMessage());
            e.printStackTrace();
        }
    }



}